博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
微信小程序中实现瀑布流布局和无限加载
阅读量:4085 次
发布时间:2019-05-25

本文共 4228 字,大约阅读时间需要 14 分钟。

瀑布流布局是一种比较流行的页面布局方式,最典型的就是Pinterest.com,每个卡片的高度不都一样,形成一种参差不齐的美感。 在HTML5中,我们可以找到很多基于jQuery之类实现的瀑布流布局插件,轻松做出这样的布局形 ...

瀑布流布局是一种比较流行的页面布局方式,最典型的就是Pinterest.com,每个卡片的高度不都一样,形成一种参差不齐的美感。

在HTML5中,我们可以找到很多基于jQuery之类实现的瀑布流布局插件,轻松做出这样的布局形式。在微信小程序中,我们也可以做出这样的效果,不过由于小程序框架的一些特性,在实现思路上还是有一些差别的。

今天我们就来看一下如何在小程序中去实现这种瀑布流布局:

小程序瀑布流布局

我们要实现的是一个固定2列的布局,然后将图片数据动态加载进这两列中(而加载进来的图片,会根据图片实际的尺寸,来决定到底是放在左列还是右列中)。

/* 单个图片容器的样式 */.img_item {  width: 48%;  margin: 1%;  display: inline-block;  vertical-align: top;}

我们知道,在HTML中,我们要动态加载图片的话,通常会使用new Image()创建一个图片对象,然后通过它来动态加载一个url指向的图片,并获取图片的实际尺寸等信息。而在小程序框架中,并没有提供相应的JS对象来处理图片加载。其实我们可以借助wxml中的<image>组件来完成这样的功能,虽然有点绕,但还是能满足我们的功能要求的。

我们可以在Page中通过数据绑定,来传递要加载的图片信息到wxml中,让<image>组件去加载图片资源,然后当图片加载完成的时候,通过bindload指定的事件处理函数来做进一步处理。

我们来看一下Page文件中定义的onImageLoad函数。在其中,我们可以从传入的事件对象e上,获取到<image>组件的丰富信息,包括通过它加载进来的图片的实际大小。然后我们将图片按照页面上实际需要显示的尺寸,计算出同比例缩放后的尺寸。接着,我们可以根据左右两列目前累积的内容高度,来决定把当前加载进来的图片放到哪一边。

let col1H = 0;let col2H = 0;Page({    data: {        scrollH: 0,        imgWidth: 0,        loadingCount: 0,        images: [],        col1: [],        col2: []    },    onLoad: function () {        wx.getSystemInfo({            success: (res) => {                let ww = res.windowWidth;                let wh = res.windowHeight;                let imgWidth = ww * 0.48;                let scrollH = wh;                this.setData({                    scrollH: scrollH,                    imgWidth: imgWidth                });                //加载首组图片                this.loadImages();            }        })    },    onImageLoad: function (e) {        let imageId = e.currentTarget.id;        let oImgW = e.detail.width;         //图片原始宽度        let oImgH = e.detail.height;        //图片原始高度        let imgWidth = this.data.imgWidth;  //图片设置的宽度        let scale = imgWidth / oImgW;        //比例计算        let imgHeight = oImgH * scale;      //自适应高度        let images = this.data.images;        let imageObj = null;        for (let i = 0; i < images.length; i++) {            let img = images[i];            if (img.id === imageId) {                imageObj = img;                break;            }        }        imageObj.height = imgHeight;        let loadingCount = this.data.loadingCount - 1;        let col1 = this.data.col1;        let col2 = this.data.col2;        //判断当前图片添加到左列还是右列        if (col1H <= col2H) {            col1H += imgHeight;            col1.push(imageObj);        } else {            col2H += imgHeight;            col2.push(imageObj);        }        let data = {            loadingCount: loadingCount,            col1: col1,            col2: col2        };        //当前这组图片已加载完毕,则清空图片临时加载区域的内容        if (!loadingCount) {            data.images = [];        }        this.setData(data);    },    loadImages: function () {        let images = [            { pic: "../../images/1.png", height: 0 },            { pic: "../../images/2.png", height: 0 },            { pic: "../../images/3.png", height: 0 },            { pic: "../../images/4.png", height: 0 },            { pic: "../../images/5.png", height: 0 },            { pic: "../../images/6.png", height: 0 },            { pic: "../../images/7.png", height: 0 },            { pic: "../../images/8.png", height: 0 },            { pic: "../../images/9.png", height: 0 },            { pic: "../../images/10.png", height: 0 },            { pic: "../../images/11.png", height: 0 },            { pic: "../../images/12.png", height: 0 },            { pic: "../../images/13.png", height: 0 },            { pic: "../../images/14.png", height: 0 }        ];        let baseId = "img-" + (+new Date());        for (let i = 0; i < images.length; i++) {            images[i].id = baseId + "-" + i;        }        this.setData({            loadingCount: images.length,            images: images        });    }})

这里是显示在两列图片的wxml代码,我们可以看到在<scroll-view>组件上,我们通过使用bindscrolltolower设置了事件监听函数,当滚动到底部的时候,会触发loadImages去再加载下一组的图片数据,这样就形成了无限的加载:

好了,挺简单的一个例子,如果你有更好的方法,不吝分享一下哦。

完整代码可以在我的Github下载:

文件下载:

转载地址:http://cnhni.baihongyu.com/

你可能感兴趣的文章
React 和 ReactNative 的渲染机制/ ReactNative 与原生之间的通信 / 如何自定义封装原生组件/RN中的多线程
查看>>
JavaScript实现DOM树的深度优先遍历和广度优先遍历
查看>>
webpack4 中的 React 全家桶配置指南,实战!
查看>>
react 设置代理(proxy) 实现跨域请求
查看>>
通过试题理解JavaScript
查看>>
webpack的面试题总结
查看>>
实践这一次,彻底搞懂浏览器缓存机制
查看>>
Koa2教程(常用中间件篇)
查看>>
React Hooks 完全指南
查看>>
React16常用api解析以及原理剖析
查看>>
教你发布你npm包
查看>>
nvm 和 nrm 的安装与使用
查看>>
React Hooks 一步到位
查看>>
React Redux常见问题总结
查看>>
前端 DSL 实践指南
查看>>
ReactNative: 自定义ReactNative API组件
查看>>
cookie
查看>>
总结vue知识体系之实用技巧
查看>>
PM2 入门
查看>>
掌握 TS 这些工具类型,让你开发事半功倍
查看>>